<template>
    <AdminSkeleton>
        <template #header>
            <div class="params">
                <el-form :model="pgform" label-width="auto">                    
                    <el-form-item label="班组:" size="small">
                        <el-config-provider :value-on-clear="''" :empty-values="['',undefined, null]">
                            <el-select v-model="pgform.persongroup" 
                                clearable
                                placeholder="请选择班组" size="small" style="width: 150px"
                                @visible-change="changePg"                        
                            >
                                <el-option v-for="item in useStore.pgs" :label="item.PGNAME" :value="item.PERSONGROUP" :key="item.PERSONGROUP"/>
                            </el-select>
                        </el-config-provider>
                    </el-form-item>
                    <el-form-item label="姓名:" size="small">
                        <el-input v-model="pgform.realname" size="small" style="width: 100px"/>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" size="small" @click="getUsersInfo(pgform)">查询</el-button>
                    </el-form-item>
                </el-form>
            </div>
        </template>
        <template #control>
            <Control :batchIsShow="batchIsShow" :downloadBoxShow="downloadBoxShow"
                :permObj="permObj"
                @addClick="editUser('add',{})" 
                @showDownload="showDownloadBox"                               
                @downloadExcelPaging="downloadExcelPaging(newDatasArr,'usersTable','用户信息')"
                @downloadExcelAll="downloadExcelAll(datasArr,'用户信息')"
                @batchToggleShow="batchEdit"
                @batchDel="editSubmit('batchDel',selectUsers)"
                @batchUpload="batchUpload"
            ></Control>
            <Paging :dataLength="datasLength" :countPage="countPage" :btnDisabledObj="btnDisabledObj"
                v-model:firstPage="firstPage"
                v-model:pageSize="pageSize"
                @toNext="nextPage(firstPage)"
                @toLast="lastPage(firstPage)"
                @toFirst="toFirstPage"
                @toEnd="toEndPage"
                @toSpecify="toSpecifyPage"
                @changePsize="changePageSize"
            ></Paging>
        </template>
        <template #content>
            <el-table :data="newDatasArr" style="width: 100%"  v-loading="loading" 
                @selection-change="handleSelectionChange"
                id="usersTable"
            >
                <el-table-column type="selection" width="50" v-if="selectShow"/>
                <el-table-column fixed prop="ID" label="ID" width="60" />
                <el-table-column prop="PERSONID" label="人员号" width="100" />
                <el-table-column prop="USERNAME" label="用户名" width="120" />
                <el-table-column prop="REALNAME" label="姓名" width="120" />
                <el-table-column prop="PASSWORD" label="密码" width="120">
                    <template #default="{row}">
                        <el-input v-model="row.PASSWORD" type="password" disabled ></el-input>
                    </template>
                </el-table-column>
                <el-table-column prop="REMARK" label="备注" width="120" />
                <el-table-column prop="PERSONGROUP" label="人员组" width="120" />
                <el-table-column fixed="right" label="Operations" min-width="120"
                    v-perm="permObj.update"
                >
                    <template #default="{row}">
                        <el-button type="primary" size="small" 
                            v-perm="permObj.update"
                            @click="editUser('update',row)" title="编辑"
                        >
                            <el-icon><Edit /></el-icon>
                        </el-button>
                        <el-button  type="danger" size="small" class="del" title="删除" 
                            v-perm="permObj.delete"
                            @click="editSubmit('delete',row)"
                        >
                            <el-icon><DeleteFilled /></el-icon>
                        </el-button>
                    </template>
                </el-table-column>
                <el-table-column prop="STATUS" label="状态" width="120" />
            </el-table>
        </template>
    </AdminSkeleton>
    <Drawer ref="drawerRef" :title="title" :size="size" 
        @submit="editSubmit(submitType,editForm)"
        @cancel-submit="resetForm"
    >
        <el-form :model="editForm"  
            ref="updateFormRef"
            :rules="rules"
        >
            <el-form-item label="ID" :label-width="formLabelWidth">
                <el-input v-model="editForm.ID" autocomplete="off" disabled/>
            </el-form-item>
            <el-form-item label="人员号" :label-width="formLabelWidth" prop="PERSONID">
                <el-input v-model="editForm.PERSONID" autocomplete="off" />
            </el-form-item>
            <el-form-item label="用户名" :label-width="formLabelWidth" prop="USERNAME">
                <el-input v-model="editForm.USERNAME" autocomplete="off" />
            </el-form-item>
            <el-form-item label="姓名" :label-width="formLabelWidth" prop="REALNAME"> 
                <el-input v-model="editForm.REALNAME" autocomplete="off" />
            </el-form-item>
            <el-form-item label="密码" :label-width="formLabelWidth" prop="PASSWORD" > 
                <el-input v-model="editForm.PASSWORD" autocomplete="off" type="password" show-password/>
            </el-form-item>
            <el-form-item label="备注" :label-width="formLabelWidth">
                <el-input v-model="editForm.REMARK" autocomplete="off" />
            </el-form-item>
            <el-form-item label="人员组" :label-width="formLabelWidth" prop="PERSONGROUP">
                <el-select
                    v-model="editForm.PERSONGROUP"
                    placeholder="请选择班组"
                    @visible-change="changePg"
                >
                    <el-option v-for="item in useStore.pgs" :label="item.PGNAME" :value="item.PERSONGROUP" />
                </el-select>
            </el-form-item>
            <!-- <el-form-item label="状态" :label-width="formLabelWidth">
                <el-input v-model="editForm.STATUS" autocomplete="off" />  
            </el-form-item> -->
            <el-form-item label="状态" :label-width="formLabelWidth" prop="STATUS">
                <el-select
                    v-model="editForm.STATUS"
                    placeholder="状态"
                >
                    <el-option label="活动" :value=1 />
                    <el-option label="不活动" :value=0 />
                </el-select>  
            </el-form-item>
      </el-form>
    </Drawer>
    <Dialog ref="dialogRef" :uploadKeys="uploadKeys"
        @uploadFile="uploadFile" @closeDialog="closeDialog"
        @batchUpdate="editSubmit('batchUpdate',uploadTable)"
        @batchAdd="editSubmit('batchAdd',uploadTable)"
        @downloadTemplate="downloadTemplate('upload-table','用户信息导入模板')"
    > 
        <el-table :data="uploadTable" style="width: 100%" ref="dialogTableRef" id="upload-table">
            <el-table-column fixed prop="ID" label="ID" width="60" />
            <el-table-column prop="PERSONID" label="人员号" width="100" />
            <el-table-column prop="USERNAME" label="用户名" width="120" />
            <el-table-column prop="REALNAME" label="姓名" width="120" />
            <el-table-column prop="PASSWORD" label="密码" width="120">
                <template #default="{row}">
                    <el-input v-model="row.PASSWORD" type="password" disabled></el-input>
                </template>
            </el-table-column>
            <el-table-column prop="REMARK" label="备注" width="120" />
            <el-table-column prop="PERSONGROUP" label="人员组" width="120" />
            <el-table-column prop="STATUS" label="状态" width="120" />             
        </el-table>
    </Dialog>
</template>

<script setup>
import AdminSkeleton from '@/components/AdminSkeleton.vue' 
import Control from '@/components/Control.vue'
import Paging from '@/components/Paging.vue'
import Drawer from '@/components/Drawer.vue'
import { reactive,ref,watch  } from 'vue'
import {getPg,getUsers,handleUser,batchHandleUser} from '@/utils/adminApi/usrs'
import { mainStore } from '@/stores/store'
import {msgOpen} from '@/utils/msg'
import {confirm ,confirmBatch} from '@/utils/confirm'
import {exportClickFromTableId,exportClickFromDatas} from '@/utils/downloadExcel'
import {paging} from '@/utils/paging'
import Dialog from '@/components/Dialog.vue'
import {encryptPassword} from '@/utils/enctyption'
import { objCopy } from '@/utils/objCopy'
import {isEqual} from '@/utils/objIsEqual'

//权限对象--用于控制按钮显示
const permObj = {
    add:{name:'Users',type:'add'},
    update:{name:'Users',type:'update'},
    delete:{name:'Users',type:'delete'}
}

const useStore = mainStore()

const {
    datasArr, 
    datasLength,
    firstPage,
    pageSize, 
    countPage,
    newDatasArr, 
    btnDisabledObj,
    pagingPreprocessing,
    nextPage,
    lastPage,
    toFirstPage,
    toEndPage,
    toSpecifyPage,
    changePageSize
} = paging() //分页

let pgform = reactive({
    persongroup: '',
    realname: ''
})

let loading = ref(false)
//获取班组信息
const changePg = async ()=>{  
    if(!useStore.pgs.length){
        let pgs = await getPg()
        useStore.setPgs(pgs.datas.pgs)       
    }    
}

//查询用户信息
let title = ref("")
let size = ref("35%")
let formLabelWidth = ref("80")

/**
 * 查询用户
 * @param {Object} data form表单信息
 */
const getUsersInfo = async (data)=>{
    // console.log(data)
    loading.value = true
    let usersInfo = await getUsers(data)
    // console.log(usersInfo)    
    pagingPreprocessing(usersInfo.datas.usersInfo) //分页前置处理
    loading.value = false    
}


//编辑用户信息
let drawerRef = ref(null) //组件ref
let oldUserInfo = reactive({
    ID:'',
    PERSONID:'',
    USERNAME:'',
    REALNAME:'',
    PASSWORD:'',
    REMARK:'',
    PERSONGROUP:'',
    STATUS:''
}) //用于存储未修改前用户信息
let editForm = reactive({
    ID:'',
    PERSONID:'',
    USERNAME:'',
    REALNAME:'',
    PASSWORD:'',
    REMARK:'',
    PERSONGROUP:'',
    STATUS:''
})
let submitType = ref('')


//表单验证ref
let updateFormRef = ref(null)
//输入框验证规则
let rules = reactive({
    PERSONID: [
        { required: true, message: '请输入人员号', trigger: 'blur' },
    ],
    USERNAME: [
        { required: true, message: '请输入用户名', trigger: 'blur' },
    ],
    REALNAME: [
        { required: true, message: '请输入姓名', trigger: 'blur' },
    ],
    PASSWORD: [
        { required: true, message: '请输入密码', trigger: 'blur' },
    ],
    PERSONGROUP: [
        { required: true, message: '请选择班组', trigger: 'blur' },
    ],
    STATUS: [
        { required: true, message: '请选择状态', trigger: 'blur' },
    ]
})

//重置表单
const resetForm = ()=>{
    if(submitType.value === 'update'){
        editForm = objCopy(oldUserInfo,editForm)
    }else if(submitType.value === 'add'){
        editForm = reactive({
                    ID:'',
                    PERSONID:'',
                    USERNAME:'',
                    REALNAME:'',
                    REMARK:'',
                    PERSONGROUP:'',
                    STATUS:''
                })
    }
}

/**
 * @param {String} type 处理类型
 * @param {Object} row 行对象
 * 
 */
const editUser = (type,row)=>{
    submitType.value = type
    drawerRef.value.open()    
    if(type === 'update') {
        title.value = "编辑"
        editForm = row
        oldUserInfo = objCopy(row,oldUserInfo) //存储未修改前用户信息 
        // console.log(oldUserInfo);                
    }
    if(type === 'add') {
        title.value = "新增"
        resetForm()
    }
    // console.log(row);    
}

/**处理用户方法
 * @param {Object} data 更新用户表单对象
 * @param {String} type 处理类型
 */

let batchChangeObj = reactive({
    batchDataArr:[],        //批量处理数据
    batchPidArr:[],         //批量删除时用户角色中间表需要使用personid
    batchEditType:"search" //处理类型
})
const editSubmit = async (type,data)=>{
    // console.log(data.PASSWORD);
    submitType.value = type
    if(type === 'update' || type === 'add'){        
        updateFormRef.value.validate(async (valid)=>{
            if(!valid){
                return false
            }else{  
                let isChange = isEqual(data,oldUserInfo)
                // console.log(isEqual(data,oldUserInfo));
                if(isChange.length) {
                    let psIsChange = ref(false)
                    isChange.forEach((item)=>{
                        if(item.prop === 'PASSWORD'){
                            psIsChange.value = true
                        }
                    })
                    //密码有修改则加密
                    if(psIsChange.value) data.PASSWORD = encryptPassword(data.PASSWORD)                      
                    // console.log(data.PASSWORD)
                    drawerRef.value.showLoading()
                    let newUser = await handleUser(type,data,psIsChange.value)
                    // console.log(newUser)
                    drawerRef.value.hideLoading()
                    drawerRef.value.close()
                    newUser.status ? msgOpen(newUser.msg,'success') : msgOpen(newUser.msg) 
                    getUsersInfo(pgform) 
                }else{
                    msgOpen('未修改任何信息！')
                }                
            }
        })
    }else if(type === 'delete'){
        let res = await confirm(data.ID)
        // console.log(res);        
        if(res){
            let newUser = await handleUser(type,data)
            // console.log(newUser);
            msgOpen(newUser.msg,'success')
            getUsersInfo(pgform) 
        }
    }else if(type === 'batchDel'){
        if(!data.length){
            msgOpen('未进行勾选，请勾选！')
        }else{
            let idsArr = ref([]) //ID嵌套数组，ORACLE接收的参数必须为嵌套数组
            let personidsArr = ref([]) //PERSONID嵌套数组，ORACLE接收的参数必须为嵌套数组
            // console.log(data);
            data.forEach((item)=>{
                let idArr = ref([])
                let personidArr = ref([])
                idArr.value.push(item.ID)
                idsArr.value.push(idArr.value)
                personidArr.value.push(item.PERSONID)
                personidsArr.value.push(personidArr.value)
            })            
            batchChangeObj.batchDataArr = idsArr.value
            batchChangeObj.batchPidArr = personidsArr.value
            batchChangeObj.batchEditType = type
            let isDel = await confirmBatch(batchChangeObj.batchDataArr.length)          
            if(isDel){
                // console.log(batchChangeObj);
                let newUsers = await batchHandleUser(type,batchChangeObj)
                // console.log(newUsers);
                if(newUsers.datas.batchEditUsers.errorNum){
                    msgOpen(newUsers.msg)
                }else{
                    msgOpen(newUsers.msg +',共：' + newUsers.datas.batchEditUsers.rowsAffected + '条' ) 
                    getUsersInfo(pgform) 
                }
            }
        }
    }else if(type === 'batchUpdate' || type === 'batchAdd'){
        // console.log(data); 
        let rowsArr = ref([]) 
        let editBatchStatus = ref(true)
        for(let i = 0;i < data.length;i++){
            // console.log(data[i]);            
            if(type === 'batchUpdate' && !data[i].ID){
                msgOpen("更新用户，请填写ID！")
                editBatchStatus.value = false
                break
            }else if(type === 'batchAdd' && data[i].ID){
                msgOpen("新增用户，ID请留空！")
                editBatchStatus.value = false
                break  
            }else{
                let row
                data[i].PASSWORD = data[i].PASSWORD.length ? encryptPassword(data[i].PASSWORD) : ""//密码加密
                row = data[i] //传给后端(ORACLE也可接收数组对象，处理时SQL绑定变量须于数组对象内的KEY值一致)
                // if(type === 'batchAdd'){
                //     data[i].PASSWORD = data[i].PASSWORD ? encryptPassword(data[i].PASSWORD) : ""//密码加密
                //     row = Object.values(data[i]) //将对象值转成数组
                // }else{
                //     row = data[i] //穿给后端由后端转换
                //     // console.log(data[i]);                   
                // }                               
                // console.log(row);
                rowsArr.value.push(row)
            }
        } 
        // console.log(editBatchStatus.value);
        // console.log(rowsArr);
        
        //#region 
        /*  map不能使用break或continue，函数的设计初衷是处理数组中的每一个元素，并生成一个新的数组。
            如果允许在map中使用break或continue，那么就会破坏这一连贯性，导致生成的数组不完整或不符合预期。
        data.map((item)=>{
            if(type === 'batchUpdate' && !item.ID){
                msgOpen("更新用户，请填写ID！")
                return 
            }else if(type === 'batchAdd' && item.ID){
                msgOpen("新增用户，ID请留空！")
                return 
            }else{
                let row
                if(type === 'batchAdd'){
                    row = Object.values(item) //将对象值转成数组
                }                               
                console.log(row);
                rowsArr.value.push(row)
            }            
        }) */
        // console.log(rowsArr);
        //#endregion
        if(editBatchStatus.value){
            batchChangeObj.batchDataArr = rowsArr 
            batchChangeObj.batchEditType = type
            let newUsers = await batchHandleUser(type,batchChangeObj)  
            // console.log(newUsers);
            dialogRef.value.close()
            uploadTable = ref([])
            if(!newUsers.status){
                msgOpen(newUsers.msg)
            }else{
                newUsers.datas.batchEditUsers.rowsAffected ? msgOpen(`${newUsers.msg},共${newUsers.datas.batchEditUsers.rowsAffected}条`,"success") 
                                                            : msgOpen(newUsers.msg)
            }        
            getUsersInfo(pgform)   
        }                  
    }   
}

//批量处理
let batchIsShow = ref(false) //展示批量上传、批量删除状态
let selectShow = ref(false) //展示批量勾选状态
let selectUsers = ref([])
let dialogRef = ref(null) //组件ref
let uploadKeys = ref([
    "ID",
    "PERSONID",
    "USERNAME",
    "REALNAME",
    "PASSWORD",
    "REMARK",
    "PERSONGROUP",
    "STATUS"
])

const batchEdit = ()=>{   
    if(newDatasArr.value.length) selectShow.value = !selectShow.value
    batchIsShow.value = !batchIsShow.value
}
const handleSelectionChange = (val)=>{
    selectUsers.value = val 
}

//批量上传
let uploadTable = ref([])
const batchUpload = ()=>{
    // console.log('batchUpload');
    dialogRef.value.open()       
}
//关闭
const closeDialog = () => {
    uploadTable = ref([])
    dialogRef.value.close()
}

//接收子组件传递的excel数据，渲染至界面
let dialogTableRef = ref(null)
const uploadFile = (e)=>{       
    uploadTable = e.value   
}

//下载
let downloadBoxShow = ref(false) //展示下载框状态
const showDownloadBox = ()=>{
    downloadBoxShow.value = !downloadBoxShow.value
}
/** 
 * 下载当前页
 * @param {Array} data 导出的数据数组对象
 * @param {String} tableId table标签的ID
 * @param {String} fileName 需要命名的文件名
 */
const downloadExcelPaging = (data,tableId,fileName)=>{
    data.length ? exportClickFromTableId(tableId,fileName) : msgOpen("无数据可供下载，请先查询数据")
    /*报文件损坏 不适用于前段直接导出为Excel，适用于前后端配合使用
    try{
        let url = window.URL.createObjectURL(new Blob([ data ]))
        console.log(url);
        let link = document.createElement("a")
        link.style.display ="none"
        link.href = url
        let filename =(new Date()).getTime() + ".xlsx"
        link.setAttribute("download",filename)
        document.body.appendChild(link)
        link.click()
    } catch(err){
        console.log(err);    
    }
    */
}
/**
 * 下载全部
 * @param {Array} data 导出的数据数组对象(未进行分页)
 * @param {String} fileName 需要命名的文件名
 */
const downloadExcelAll = (data,fileName)=>{   
    if(data.length){
        let newData = JSON.parse(JSON.stringify(data)) //深拷贝
        for(let i = 0;i < newData.length;i++){
            newData[i].PASSWORD = ""
        }
        // console.log(newData);        
        exportClickFromDatas(newData,fileName)
    }else{
        msgOpen("无数据可供下载，请先查询数据")
    }
}

/**
 * 导入模版下载
 * @param tableId table标签的ID
 * @param fileName 需要命名的文件名
 */
 const downloadTemplate = (tableId,fileName)=>{
    // console.log(tableId)
    exportClickFromTableId(tableId,fileName)
}

watch([uploadTable,newDatasArr],(newTable, oldTable) => {
    // console.log(newTable[0]);
    uploadTable.value = newTable[0]
    newDatasArr.value = newTable[1]
})

</script>

<style lang="less" scoped>
.params{
    width: 100%;
    height: 100%;
    .el-form{
        width: 100%;
        height: 100%;
        display: flex;
        align-items:center;
        justify-content: flex-start;
        .el-form-item{
            margin-bottom: 0;
            margin-right: .3125rem;
        }
    }
    
}
.el-table{
    height: 95%;
}
</style>